package com.magic0610.MagicYaml;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import com.magic0610.MagicYaml.Exception.FileNotExist;
import com.magic0610.MagicYaml.Exception.InternalLoadFailedException;
import com.magic0610.MagicYaml.Exception.MagicIOException;
import com.magic0610.MagicYaml.Exception.PathMismatchException;

public class MagicYaml {
    private final File dataFolder;
    private final String internalBasePath;
    private final boolean bukkitSupport;

    /**
     * <p>初始化函数</p>
     * 
     * @param dataFolder - 数据存储目录(File)
     * @param bukkitSupport - 开启Bukkit支持，开发Bukkit插件时应保证开启(boolean)
     * 
     * @throws MagicIOException 创建数据存储目录时出错
     */
    public MagicYaml(File dataFolder, boolean bukkitSupport) {
        this.dataFolder = dataFolder;
        this.bukkitSupport = bukkitSupport;
        internalBasePath = null;
        createDataFolder(); //创建数据存储目录
    }

    /**
     * <p>初始化函数</p>
     * 
     * @param dataFolder - 数据存储目录(File)
     * @param internalBasePath - 设定内部的根目录
     * @param bukkitSupport - 开启Bukkit支持，开发Bukkit插件时应保证开启(boolean)
     * 
     * @throws MagicIOException 创建数据存储目录时出错
     */
    public MagicYaml(File dataFolder, String internalBasePath, boolean bukkitSupport) {
        this.dataFolder = dataFolder;
        this.bukkitSupport = bukkitSupport;
        createDataFolder(); //创建数据存储目录

        if (internalBasePath != null && !internalBasePath.isEmpty()) { //处理internalBasePath的格式
            internalBasePath = internalBasePath.replaceAll("\\\\", "/");
            //替换为正斜杠

            if (!internalBasePath.startsWith("/")) {
                internalBasePath = "/" + internalBasePath;
            } //开头增加正斜杠

            while (internalBasePath.endsWith("/")) {
                internalBasePath = internalBasePath.substring(0, internalBasePath.length() - 1);
            } //删除结尾的所有正斜杠

            this.internalBasePath = internalBasePath;
        } else {
            this.internalBasePath = null;
        }
    }

    /*
     * 创建数据存储目录
     * 抛出异常: MagicIOException
     */
    private void createDataFolder() {
        Path folder = dataFolder.toPath();
        if (!Files.exists(folder)) {
            try {
                Files.createDirectories(folder);
            } catch (IOException exception) {
                throw new MagicIOException(exception);
            }
        }
    }

    /**
     * <p>获取数据存储目录</p>
     * 
     * @return File - 数据存储目录
     */
    public File getDataFolder() {
        return dataFolder;
    }

    /**
     * <p>读取已经在数据文件夹中的文件</p>
     * <p>若传入的文件不存在或路径不在数据存储目录下，返回null</p>
     * 
     * @param file - 配置文件(File)
     * 
     * @return YamlConfig - 配置文件对象
     * 
     * @throws MagicIOException 获取Jar内部配置文件流失败
     * @throws InternalLoadFailedException 读取Jar内部配置文件出错
     * @throws PathMismatchException 传入的文件不在数据存储目录下
     * @throws FileNotExist 目标配置文件不存在
     */
    public YamlConfig getResource(File file) {
        if (!Functions.isFilePathLegal(file, dataFolder)) {
            throw new PathMismatchException();
        }
        if (!file.exists()) {
            throw new FileNotExist(file.getName());
        }
        YamlConfig yamlConfig = new YamlConfig(
            file, 
            internalBasePath, 
            Functions.getInternalPath(file, dataFolder), 
            bukkitSupport
        ); //合法时创建并返回
        yamlConfig.loadConfig();
        yamlConfig.updateVersion();
        return yamlConfig;
    }

    /**
     * <p>保存Jar内置配置文件到数据文件夹</p>
     * 
     * @param file - 配置文件(File)
     * @param override - 是否覆盖(boolean)
     * 
     * @return YamlConfig - 配置文件对象
     * 
     * @throws MagicIOException 获取Jar内部配置文件流失败
     * @throws PathMismatchException 传入的文件不在数据存储目录下
     * @throws InternalLoadFailedException 读取Jar内部配置文件出错
     */
    public YamlConfig saveResource(File file, boolean override) {
        if (!Functions.isFilePathLegal(file, dataFolder)) {
            throw new PathMismatchException();
        }

        String internalPath = Functions.getInternalPath(file, dataFolder); //获取Jar内部路径
        YamlConfig yamlConfig = new YamlConfig(file, internalBasePath, internalPath, bukkitSupport);
        
        if (file.exists() && !override) { //文件存在且不覆盖
            yamlConfig.loadConfig();
            yamlConfig.updateVersion();
            return yamlConfig;
        }
        
        if (!file.exists()) {
            Functions.createDirIfNotExist(file); //创建文件的所有父文件夹
        }
        
        Functions.saveInternalFile(yamlConfig, override); //保存文件
        yamlConfig.loadConfig(); //加载配置文件
        yamlConfig.updateVersion(); //更新版本号
        return yamlConfig;
    }

    /**
     * <p>保存Jar内置配置文件到数据文件夹</p>
     * 
     * @param path - 相对于数据存储目录的配置文件路径(String)
     * @param override - 是否覆盖(boolean)
     * 
     * @return YamlConfig - 配置文件对象
     * 
     * @throws MagicIOException 获取Jar内部配置文件流失败
     * @throws PathMismatchException 传入的文件不在数据存储目录下
     * @throws InternalLoadFailedException 读取Jar内部配置文件出错
     */
    public YamlConfig saveResource(String path, boolean override) {
        return saveResource(new File(dataFolder, path), override);
    }
}
